home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Almathera Ten Pack 2: CDPD 1
/
Almathera Ten on Ten - Disc 2: CDPD 1.iso
/
pd
/
351-375
/
354
/
keymacro
/
keymacro-handler.c
< prev
next >
Wrap
C/C++ Source or Header
|
1995-03-14
|
16KB
|
844 lines
/****************************************************************************
*
* KeyMacro.Handler.c ---- KeyMacro handler.
*
* Author ---------------- Olaf Barthel, MXM
* Brabeckstrasse 35
* D-3000 Hannover 71
*
* KeyMacro © Copyright 1990 by MXM; Executable program,
* documentation and source code are shareware. If you like
* this program a small donation will entitle you to receive
* updates and new programs from MXM.
*
****************************************************************************/
/* Function prototypes. */
VOID FreeString(BPTR);
BPTR CreateBSTR(char *);
BPTR CopyPath(VOID);
VOID FakeCLI(VOID);
VOID ClearPath(BPTR);
VOID StopFakery(VOID);
VOID * DeleteMacroMsg(struct MacroMessage *);
VOID * SendMacroMsg(struct MacroMessage *,struct MsgPort *);
VOID Executor(VOID);
struct InputEvent * EventHandler(struct InputEvent *);
struct MacroKey * FindMacroKey(LONG,LONG);
LONG CreateHandler(VOID);
VOID DeleteHandler(VOID);
LONG _main(VOID);
/* The magic stuff. */
#pragma regcall(EventHandler(a0))
/* Shared library identifiers. */
struct MXMBase *MXMBase;
struct IntuitionBase *IntuitionBase;
struct Library *ConsoleDevice;
extern struct ExecBase *SysBase;
/* Global handshake data. */
struct MSeg *MSeg;
struct KeyEquivalent *EquList;
/* Process<->Process communication data. */
struct Process *ExecuteProc;
struct MsgPort *ExecutePort;
/* Input device data. */
struct MsgPort *InputDevPort;
struct IOStdReq *InputRequestBlock;
struct Interrupt *InputHandler;
struct InputEvent *FakeInputEvent;
/* _main():
*
* This is the entry point to the handler process.
*/
LONG
_main()
{
struct Process *ThatsMe;
ULONG SignalSet;
struct MacroMessage *MacroMsg;
LONG SigBit;
LONG i;
/* Do I know myself? */
ThatsMe = (struct Process *)SysBase -> ThisTask;
/* Don't let anybody call us from CLI. */
if(ThatsMe -> pr_CLI)
goto Quit;
/* Can we find the global MsgPort? */
if(!(MSeg = (struct MSeg *)FindPort(PORTNAME)))
{
Forbid();
Signal(MSeg -> Father,MSeg -> RingBack);
goto Quit;
}
/* This older revision probably doesn't support
* some newer structure tags -> exit.
*/
if(MSeg -> Revision < REVISION)
{
Forbid();
Signal(MSeg -> Father,MSeg -> RingBack);
goto Quit;
}
/* The MsgPort is already owned by someone
* else.
*/
if(MSeg -> Port . mp_Flags & PA_SIGNAL)
{
Forbid();
Signal(MSeg -> Father,MSeg -> RingBack);
goto Quit;
}
/* Open mxm.library. */
if(!(MXMBase = (struct MXMBase *)OpenLibrary("mxm.library",34)))
{
Forbid();
Signal(MSeg -> Father,MSeg -> RingBack);
goto Quit;
}
/* Initialize the input.device handler. */
if(!CreateHandler())
{
DeleteHandler();
CloseLibrary((struct Library *)MXMBase);
Forbid();
Signal(MSeg -> Father,MSeg -> RingBack);
goto Quit;
}
/* Extract shared library identifiers. */
IntuitionBase = (struct IntuitionBase *)MXMBase -> IntuitionBase;
ConsoleDevice = (struct Library *)MXMBase -> ConsoleDevice;
/* Allocate a fake InputEvent structure. */
if(!(FakeInputEvent = (struct InputEvent *)AllocRem(sizeof(struct InputEvent),MEMF_PUBLIC)))
{
DeleteHandler();
CloseLibrary((struct Library *)MXMBase);
Forbid();
Signal(MSeg -> Father,MSeg -> RingBack);
goto Quit;
}
/* Allocate a signal bit. */
if((SigBit = AllocSignal(-1)) == -1)
{
FreeRem(FakeInputEvent);
DeleteHandler();
CloseLibrary((struct Library *)MXMBase);
Forbid();
MSeg -> Child = NULL;
Signal(MSeg -> Father,MSeg -> RingBack);
goto Quit;
}
/* Start the executing process. */
MSeg -> Child = (struct Task *)ThatsMe;
if(!(ExecuteProc = (struct Process *)CreateFuncProc("KeyMacro.exec",10,Executor,4000)))
{
FreeSignal(SigBit);
FreeRem(FakeInputEvent);
DeleteHandler();
CloseLibrary((struct Library *)MXMBase);
Forbid();
MSeg -> Child = NULL;
Signal(MSeg -> Father,MSeg -> RingBack);
goto Quit;
}
/* Wait for handshake signal. */
Wait(SIG_SHAKE);
/* Process creation failed. */
if(!ExecuteProc)
{
FreeSignal(SigBit);
FreeRem(FakeInputEvent);
DeleteHandler();
CloseLibrary((struct Library *)MXMBase);
Forbid();
MSeg -> Child = NULL;
Signal(MSeg -> Father,MSeg -> RingBack);
goto Quit;
}
/* Now we are truly running. */
Signal(MSeg -> Father,MSeg -> RingBack);
MSeg -> Father = NULL;
/* Re-init the MsgPort flags. */
MSeg -> Port . mp_Flags = PA_SIGNAL;
MSeg -> Port . mp_SigBit = SigBit;
MSeg -> Port . mp_SigTask = MSeg -> Child;
/* Wait until somebody kicks us out. */
FOREVER
{
SignalSet = Wait(SIG_CLOSE | SIG_PORT);
/* We are to shut down. */
if(SignalSet & SIG_CLOSE)
{
FreeSignal(SigBit);
FreeRem(FakeInputEvent);
DeleteHandler();
if(ExecuteProc)
{
Signal((struct Task *)ExecuteProc,SIG_CLOSE);
Wait(SIG_SHAKE);
}
CloseLibrary((struct Library *)MXMBase);
Forbid();
Signal(MSeg -> Father,SIG_CLOSE);
goto Quit;
}
/* A message arrived at our home port. */
if(SignalSet & SIG_PORT)
{
/* Walk through the list of messages. */
while(MacroMsg = (struct MacroMessage *)GetMsg(&MSeg -> Port))
{
/* Execute a keyboard macro. */
if(MacroMsg -> mm_Type == MM_INPUT)
{
struct MacroKey *TempMacroKey = MacroMsg -> mm_MacroKey;
if(TempMacroKey)
{
/* Let the execute process run the command. */
if(TempMacroKey -> mk_Type == MK_COMMAND)
{
struct MacroMessage CommandMsg;
CommandMsg . mm_Type = MM_EXECUTE;
CommandMsg . mm_FileName = TempMacroKey -> mk_String;
CommandMsg . mm_WindowName = TempMacroKey -> mk_Window;
SendMacroMsg(&CommandMsg,ExecutePort);
}
/* Build a keyboard macro. */
if(TempMacroKey -> mk_Type == MK_WORD)
{
InputRequestBlock -> io_Command = IND_WRITEEVENT;
InputRequestBlock -> io_Data = (APTR)FakeInputEvent;
memset(FakeInputEvent,0,sizeof(struct InputEvent));
FakeInputEvent -> ie_Class = IECLASS_RAWKEY;
for(i = 0 ; i < strlen(TempMacroKey -> mk_String) ; i++)
if(InvertKey(TempMacroKey -> mk_String[i],FakeInputEvent,IK_USEIKM,NULL))
DoIO(InputRequestBlock);
}
}
}
/* This is a request to update the
* macro keys.
*/
if(MacroMsg -> mm_Type == MM_UPDATE)
{
if(MSeg -> MacroList)
{
for(i = 0 ; i < MSeg -> NumMacros ; i++)
{
if(MSeg -> MacroList[i] . mk_Type == MK_UNUSED)
continue;
if(MSeg -> MacroList[i] . mk_String)
FreeRem(MSeg -> MacroList[i] . mk_String);
if(MSeg -> MacroList[i] . mk_Window)
FreeRem(MSeg -> MacroList[i] . mk_Window);
}
FreeRem(MSeg -> MacroList);
}
MSeg -> NumMacros = MacroMsg -> mm_NumMacros;
MSeg -> MacroList = MacroMsg -> mm_MacroList;
}
/* Remove the message. */
DeleteMacroMsg(MacroMsg);
}
}
}
Quit: ;
}
/* FreeString(Byte):
*
* Frees the memory occupied by the contents of a BSTR.
*/
VOID
FreeString(BPTR Byte)
{
LONG *Ptr = (LONG *)BADDR(Byte);
FreeMem(Ptr - 1,Ptr[-1]);
}
/* CreateBSTR(s):
*
* Allocates enough memory to hold the contents of
* a given string and makes it a BSTR.
*/
BPTR
CreateBSTR(char *s)
{
LONG Length = strlen(s);
LONG BlockLength = (Length + 8) & ~3;
char *Byte;
if(!(Byte = (char *)AllocMem(BlockLength,MEMF_PUBLIC | MEMF_CLEAR)))
return(NULL);
*(LONG *)Byte = BlockLength;
Byte[4] = Length;
strncpy(Byte + 5,s,Length);
return((LONG)(Byte + 4) >> 2);
}
/* CopyPath():
*
* Builds a fake pathlist inherited from any valid
* CLI process or Workbench.
*/
BPTR
CopyPath()
{
struct Process *Father;
struct CommandLineInterface *CLI;
BPTR *Next1,*Next2,*Last,NewPath = NULL;
Last = &NewPath;
/* If using ARP this will also give us a valid
* pathlist.
*/
if(!(Father = (struct Process *)FindTask("Workbench")))
if(!(Father = (struct Process *)FindTask("ARP Shell Process")))
if(!(Father = (struct Process *)FindTask("New CLI")))
if(!(Father = (struct Process *)FindTask("Initial CLI")))
return(NULL);
if(!(CLI = (struct CommandLineInterface *)BADDR(Father -> pr_CLI)))
return(NULL);
for(Next1 = (BPTR *)BADDR(CLI -> cli_CommandDir) ; Next1 ; Next1 = (BPTR *)BADDR(*Next1))
{
if(!(Next2 = (BPTR *)AllocMem(2 * sizeof(BPTR),MEMF_PUBLIC | MEMF_CLEAR)))
break;
*Last = (LONG)Next2 >> 2;
Last = Next2;
Next2[1] = (BPTR)DupLock(Next1[1]);
Next2[0] = NULL;
}
return(NewPath);
}
/* FakeCLI():
*
* Creates a fake CLI structure for our process. This
* includes pathlist, currentdir, prompt and stack.
*/
VOID
FakeCLI()
{
struct CommandLineInterface *CLI;
struct Process *MyProcess = (struct Process *)SysBase -> ThisTask;
if(!(CLI = (struct CommandLineInterface *)AllocMem(sizeof(struct CommandLineInterface),MEMF_PUBLIC | MEMF_CLEAR)))
return;
MyProcess -> pr_CLI = (LONG)CLI >> 2;
CLI -> cli_SetName = CreateBSTR("SYS:");
CLI -> cli_Prompt = CreateBSTR("%N> ");
CLI -> cli_DefaultStack = 4000;
CurrentDir(Lock("SYS:",ACCESS_READ));
CLI -> cli_CommandDir = CopyPath();
}
/* ClearPath(InitPath):
*
* Frees the contents of our fake pathlist.
*/
VOID
ClearPath(BPTR InitPath)
{
BPTR *Next,*Path;
for(Path = (BPTR *)BADDR(InitPath) ; Path ; Path = Next)
{
Next = (BPTR *)BADDR(Path[0]);
if(Path[1])
UnLock(Path[1]);
FreeMem(Path,2 * sizeof(BPTR));
}
}
/* StopFakery():
*
* Removes the contents of our fake CLI structure.
*/
VOID
StopFakery()
{
BPTR MyCD = (BPTR)CurrentDir(NULL);
struct Process *MyProcess = (struct Process *)SysBase -> ThisTask;
struct CommandLineInterface *CLI = (struct CommandLineInterface *)BADDR(MyProcess -> pr_CLI);
if(!CLI)
return;
if(MyCD)
UnLock(MyCD);
FreeString(CLI -> cli_SetName);
FreeString(CLI -> cli_Prompt);
ClearPath(CLI -> cli_CommandDir);
MyProcess -> pr_CLI = NULL;
FreeMem(CLI,sizeof(struct CommandLineInterface));
}
/* DeleteMacroMsg(scm_Msg):
*
* Remove a message from memory.
*/
VOID *
DeleteMacroMsg(struct MacroMessage *scm_Msg)
{
if(scm_Msg && scm_Msg -> mm_Message . mn_Node . ln_Name == (char *)scm_Msg)
FreeRem(scm_Msg);
return(NULL);
}
/* SendMacroMsg(scm_Msg,scm_Port):
*
* Post a cloned macro message to a MsgPort.
*/
VOID *
SendMacroMsg(struct MacroMessage *scm_Msg,struct MsgPort *scm_Port)
{
struct MacroMessage *scm_TempMsg = (struct MacroMessage *)AllocRem(sizeof(struct MacroMessage),MEMF_PUBLIC | MEMF_CLEAR);
if(scm_TempMsg)
{
CopyMem(scm_Msg,scm_TempMsg,sizeof(struct MacroMessage));
scm_TempMsg -> mm_Message . mn_Node . ln_Name = (char *)scm_TempMsg;
scm_TempMsg -> mm_Message . mn_ReplyPort = NULL;
scm_TempMsg -> mm_Message . mn_Length = sizeof(struct MacroMessage);
PutMsg(scm_Port,(struct Message *)scm_TempMsg);
}
return((VOID *)scm_TempMsg);
}
/* Executor():
*
* This is the dummy process to execute programs.
*/
VOID
Executor()
{
ULONG SignalSet;
BPTR NIL;
struct MacroMessage *ExecuteMsg;
struct Window *TheWindow;
char TempLine[300];
geta4();
/* Try to allocate a port (we can't use our builtin
* DOS port since we are actually calling DOS
* routines which may mix up the messages coming
* in).
*/
if(!(ExecutePort = (struct MsgPort *)CreatePort(NULL,0)))
{
Forbid();
ExecuteProc = NULL;
Signal(MSeg -> Child,SIG_SHAKE);
goto Quit;
}
/* Open the NULL-Handler. */
if(!(NIL = Open("NULL:",MODE_NEWFILE)))
{
Forbid();
ExecuteProc = NULL;
Signal(MSeg -> Child,SIG_SHAKE);
DeletePort(ExecutePort);
goto Quit;
}
/* Pretend to be a CLI. */
FakeCLI();
{
struct Process *ThatsMe = (struct Process *)SysBase -> ThisTask;
/* These are inherited from the father process,
* we had better cleared them out.
*/
ThatsMe -> pr_ConsoleTask = (APTR)DeviceProc("NULL:");
ThatsMe -> pr_WindowPtr = (APTR)-1;
/* This path leads nowhere. */
ThatsMe -> pr_CIS = NIL;
ThatsMe -> pr_COS = NIL;
}
/* We're on the scene now. */
Signal(MSeg -> Child,SIG_SHAKE);
FOREVER
{
SignalSet = Wait(SIG_CLOSE | (1 << ExecutePort -> mp_SigBit));
/* Shut down? */
if(SignalSet & SIG_CLOSE)
{
StopFakery();
Close(NIL);
DeletePort(ExecutePort);
ExecuteProc = NULL;
Forbid();
Signal(MSeg -> Child,SIG_SHAKE);
goto Quit;
}
/* Execute a command? */
while(ExecuteMsg = (struct MacroMessage *)GetMsg(ExecutePort))
{
TheWindow = NULL;
/* Try to find a matching window title. */
if(ExecuteMsg -> mm_WindowName)
{
ULONG IntuiLock;
struct Screen *ExScreen;
struct Window *ExWindow;
IntuiLock = LockIBase(NULL);
ExScreen = IntuitionBase -> FirstScreen;
do
{
ExWindow = ExScreen -> FirstWindow;
do
{
if(!UStrCmp(ExecuteMsg -> mm_WindowName,ExWindow -> Title))
{
UnlockIBase(IntuiLock);
TheWindow = ExWindow;
goto SkipLoop;
}
}
while(ExWindow = ExWindow -> NextWindow);
}
while(ExScreen = ExScreen -> NextScreen);
UnlockIBase(IntuiLock);
}
/* No chance, execute the command. */
strcpy(TempLine,"C:Run <NULL: >NULL: ");
strcat(TempLine,ExecuteMsg -> mm_FileName);
Execute(TempLine,NULL,NIL);
SkipLoop: DeleteMacroMsg(ExecuteMsg);
/* Found a window? Bring it to the front. */
if(TheWindow)
{
WindowToFront(TheWindow);
ScreenToFront(TheWindow -> WScreen);
ActivateWindow(TheWindow);
}
}
}
/* Finished, fall through. */
Quit: ;
}
/* FindMacroKey(Code,Qualifier):
*
* Find a macro key entry in the linked list of
* macro key structures.
*/
struct MacroKey *
FindMacroKey(LONG Code,LONG Qualifier)
{
LONG i;
if(!MSeg -> MacroList)
return(NULL);
for(i = 0 ; i < MSeg -> NumMacros ; i++)
{
if(MSeg -> MacroList[i] . mk_Type == MK_UNUSED)
continue;
if(MSeg -> MacroList[i] . mk_CommandKey == Code && (Qualifier & MSeg -> MacroList[i] . mk_CommandQualifier) == MSeg -> MacroList[i] . mk_CommandQualifier)
return(&MSeg -> MacroList[i]);
}
return(NULL);
}
/* EventHandler(Event):
*
* The input event handler.
*/
struct InputEvent *
EventHandler(struct InputEvent *Event)
{
struct MacroKey *HandlerKey;
/* This is an interrupt, let's start with the register
* saving.
*/
int_start();
if(Event -> ie_Class == IECLASS_RAWKEY && !(Event -> ie_Code & IECODE_UP_PREFIX))
{
if(HandlerKey = (struct MacroKey *)FindMacroKey(Event -> ie_Code,Event -> ie_Qualifier))
{
struct MacroMessage HandlerMsg;
HandlerMsg . mm_Type = MM_INPUT;
HandlerMsg . mm_MacroKey= HandlerKey;
SendMacroMsg(&HandlerMsg,&MSeg -> Port);
Event -> ie_Class = IECLASS_NULL;
}
}
/* Restore the registers. */
int_end();
return(Event);
}
/* CreateHandler():
*
* Initialize the input event handler.
*/
LONG
CreateHandler()
{
/* The basic initialization. */
if(!(InputDevPort = (struct MsgPort *)CreatePort(NULL,0)))
return(FALSE);
if(!(InputRequestBlock = (struct IOStdReq *)CreateStdIO(InputDevPort)))
return(FALSE);
if(OpenDevice("input.device",0,(struct IORequest *)InputRequestBlock,0))
return(FALSE);
if(!(InputHandler = (struct Interrupt *)AllocRem(sizeof(struct Interrupt),MEMF_PUBLIC | MEMF_CLEAR)))
return(FALSE);
/* Build the input handler. */
InputHandler -> is_Code = (VOID *)EventHandler;
InputHandler -> is_Node . ln_Pri = 51;
InputHandler -> is_Node . ln_Name = "KeyMacro-Handler";
/* Add the handler. */
InputRequestBlock -> io_Command = IND_ADDHANDLER;
InputRequestBlock -> io_Data = (APTR)InputHandler;
if(DoIO((struct IORequest *)InputRequestBlock))
return(FALSE);
return(TRUE);
}
/* DeleteHandler():
*
* Remove the input event handler.
*/
VOID
DeleteHandler()
{
/* Remove the input handler. */
if(InputRequestBlock)
{
if(InputRequestBlock -> io_Device)
{
InputRequestBlock -> io_Command = IND_REMHANDLER;
InputRequestBlock -> io_Data = (APTR)InputHandler;
DoIO((struct IORequest *)InputRequestBlock);
CloseDevice((struct IORequest *)InputRequestBlock);
}
DeleteStdIO(InputRequestBlock);
}
/* Free the last memory. */
if(InputHandler)
FreeRem(InputHandler);
if(InputDevPort)
DeletePort(InputDevPort);
}